package com.nobuyme.box.util;

import android.os.Handler;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;


/**
 * Created by Administrator on 2017/6/20.
 */
public class DriveControlLattice {
    private static DriveControlLattice m_Instance = null;
    private static final String TAG = "DriveControlLattice";
    public static final String DATA_TYPE_DRIVE = "DRIVE_BOARD_LATTICE";
    private static final int STATUS_NOT_BUSY           = 0;      //
    private static final int QUERY_GROUP_OVERTIME           = 1;      //

    /// <summary>
    /// 包头
    /// </summary>
    public static final byte CMD_STX = 0x02;
    /// <summary>
    /// 包尾
    /// </summary>
    public static final byte CMD_ETX = 0x03;

    /// <summary>
    /// 查询板子
    /// </summary>
    public static final byte CMD_QueryBoard = 0x00;
    /// <summary>
    /// 查询指定板子的格子
    /// </summary>
    public static final byte CMD_QueryLattice = 0x10;

    public static final byte CMD_LIGHT_SET = 0x20;

    public static final byte CMD_LATTICE_NUM_SET = 0x30;

    /// <summary>
    /// 打开格子门
    /// </summary>
    public static final byte CMD_LatticeOnOff = 0x40;

    public static final int CMD_QUERY_BASIC                       = 10;      // 基本查询
    public static final int CMD_QUERY_CABINET                    = 11;      // 柜子查询
    public static final int CMD_SCAN_LIGHT_SET                   = 12;      //扫描灯设置
    public static final int CMD_CABINETNO_SET                    = 13;   // 柜号设置
    public static final int CMD_CABINETNO_ON                    = 14;   // 柜号开关

    public static final int QUERY_BASIC_NORMAL               = 0;    //正常
    public static final int QUERY_BASIC_EEPROM_ERR           = 1;      //为 EEPROM 数据未设置
    public static final int QUERY_BASIC_NMOS_ERR            = 2;      //为 Nmos 管损坏
    public static final int QUERY_BASIC_PMOS_ERR           = 4;      //为 Pmos 管损坏


    public static final int SHIP_STATUS_SHIPING          = -1;
    public static final int SHIP_STATUS_SUCCESS   = 0;
    public static final int SHIP_STATUS_SLOTNO_NMOS_ERR            = 1;      //为 Nmos 管损坏
    public static final int SHIP_STATUS_SLOTNO_PMOS_ERR           = 2;      //为 Pmos 管损坏
    public static final int SHIP_STATUS_SLOTNO_NO_CURRENT          = 3;      //为电磁阀损坏 没有电流
    public static final int SHIP_STATUS_SLOTNO_LIMITSWITCH_DAMAGE   = 4;      //为限位开关损坏
    public static final int SHIP_STATUS_SLOTNO_NOTEXIST           = 5;      //柜号不存在
    public static final int SHIP_STATUS_SLOTNO_EXCESIVECURRENT   = 6;      //为电流过大
    public static final int SHIP_STATUS_FAIL   = 8;

    public static final int STATUS_SLOTNO_NORMAL           = 0;      //
    public static final int STATUS_SLOTNO_NOTEXIST         = 255;      //



//    public static final int SHIP_STATUS_SUCCESS          = 2;
//    public static final int SHIP_STATUS_FAIL             = 3;

    private volatile int m_iCmdType = -1;

    private volatile boolean m_bIsShipping = false;
    private volatile boolean m_bHaveSlotInfo = false;
    private volatile int m_iQuerySlotNo = 0;
    private volatile int m_iShipSlotNo = 0;

    private volatile boolean m_bQueryingAllSlotNo = false;
    private volatile boolean m_bIsBusy = false;
    private volatile String m_strGroupNumber = "01";

    private volatile String m_readData = "";
    private volatile List<String> m_groupList = new ArrayList<>();

    private Timer m_TimerGetData = null;
    private TimerTask m_TimerTaskGetData = null;



    public static synchronized DriveControlLattice getInstance() {
        if (null == m_Instance) {
            m_Instance = new DriveControlLattice();
        }
        return m_Instance;
    }

    public void init(Handler handlerReceive) {

    }

    public void deInit() {
        m_readData = "";
    }

    private byte RandNum()
    {
        Random ran = new Random();
        return (byte)ran.nextInt(255);
    }

    public boolean isQueryingAllSlotNo() {
        return m_bQueryingAllSlotNo;
    }

    public int getCmdType() {
        return m_iCmdType;
    }

    public void ship(int slotNo) {
        int iSlotNo = 0;
        if (slotNo < 100) {
            iSlotNo = slotNo;
            m_strGroupNumber = "00";
        } else if (slotNo < 200) {
            iSlotNo = slotNo - 100;
            m_strGroupNumber = "01";
        } else if (slotNo > 300) {
            iSlotNo = slotNo - 200;
            m_strGroupNumber = "02";
        } else if (slotNo < 400) {
            iSlotNo = slotNo - 300;
            m_strGroupNumber = "03";
        } else if (slotNo < 500) {
            iSlotNo = slotNo - 400;
            m_strGroupNumber = "04";
        } else if (slotNo < 600) {
            iSlotNo = slotNo - 500;
            m_strGroupNumber = "05";
        } else if (slotNo < 700) {
            iSlotNo = slotNo - 600;
            m_strGroupNumber = "06";
        } else if (slotNo < 800) {
            iSlotNo = slotNo - 700;
            m_strGroupNumber = "07";
        } else if (slotNo < 900) {
            iSlotNo = slotNo - 800;
            m_strGroupNumber = "08";
        }  else if (slotNo < 1000) {
            iSlotNo = slotNo - 900;
            m_strGroupNumber = "09";
        }
        else {

        }
        LatticeOnOff(m_strGroupNumber,iSlotNo);
    }

    public byte getSumVerify(byte[] data)
    {
        byte by = 0;
        for (int i = 0; i < data.length; i++)
        {
            by += data[i];
        }
        return (byte)(by);
    }

    public String getCRCXOR(String hexData) {
        return TcnUtility.getCheckXOR(hexData);
    }

    public static byte getBCC(byte[] data)
    {
        if (data == null) return 0;
        int length = data.length;
        if (length == 0) return 0;
        if (length == 1) return data[0];
        byte bcc = data[0];
        for (int i = 1; i < length; i++)
        {
            bcc ^= data[i];
        }
        return bcc;
    }

    private byte[] AssemblyCMD(byte CMD, byte[] data)
    {
        byte[] CmdData = null;
        if (data != null)
        {
            CmdData = new byte[data.length + 6];
            System.arraycopy(data, 0, CmdData, 3, data.length);
            CmdData[CmdData.length - 3] = getSumVerify(data);
        }
        else {
            CmdData = new byte[5];
        }
        CmdData[0] = CMD_STX;
        CmdData[1] = (byte)(CmdData.length - 4);
        CmdData[2] = CMD;

        CmdData[CmdData.length - 2] = CMD_ETX;
        byte[] sum = new byte[CmdData.length - 1];


        System.arraycopy(CmdData, 0, sum, 0, sum.length);
        CmdData[CmdData.length - 1] = getBCC(sum);
        return CmdData;
    }

    private byte[] getSendCMD(byte CMD, byte[] data)
    {
        byte[] SendData = null;
        SendData = AssemblyCMD(CMD, data);
       return SendData;
    }

    /// <summary>
    /// 查询板子
    /// </summary>
    /// <param name="addr"></param>
    /// <param name="BoxNo"></param>
    /// <param name="ResData"></param>
    /// <returns></returns>
    public byte[] QueryBoard(String hexAddr)
    {
        m_iCmdType = CMD_QUERY_BASIC;
        byte[] bAddrArry = TcnUtility.hexStringToBytes(hexAddr);
        byte bAddr = bAddrArry[0];
        byte bBoxNo = (byte)RandNum();
        byte[] send = new byte[] { bAddr, bBoxNo, (byte)((bAddr + bBoxNo) * 2), RandNum(), RandNum() };
        return getSendCMD(CMD_QueryBoard, send);
    }
    /// <summary>
    /// 查询命令 格子
    /// </summary>
    /// <returns></returns>
    public byte[] QueryLattice(String hexAddr, int BoxNo)
    {
        m_iCmdType = CMD_QUERY_CABINET;
        m_iQuerySlotNo = BoxNo;
        byte[] bAddrArry = TcnUtility.hexStringToBytes(hexAddr);
        byte bAddr = bAddrArry[0];
        byte bBoxNo = (byte)BoxNo;
        byte[] send = new byte[] { bAddr, bBoxNo, (byte)((bAddr + bBoxNo) * 2), RandNum(), RandNum() };
        return getSendCMD(CMD_QueryLattice, send);
    }

    /// <summary>
    /// 扫描灯设置命令 格子
    /// </summary>
    /// <returns></returns>
    public byte[] LightSet(String hexAddr, String hexMinRow, String hexMaxRow)
    {
        m_iCmdType = CMD_SCAN_LIGHT_SET;

        byte[] bAddrArry = TcnUtility.hexStringToBytes(hexAddr);
        byte bAddr = bAddrArry[0];
        byte[] bMinrArry = TcnUtility.hexStringToBytes(hexMinRow);
        byte bMin = bMinrArry[0];
        byte[] bMaxrArry = TcnUtility.hexStringToBytes(hexMaxRow);
        byte bMax = bMaxrArry[0];
        byte[] send = new byte[] { bAddr, bMin, bMax,0, RandNum(), RandNum() };
        send[3] = (byte)(((bAddr + bMin) * 2 + send[2]) * 4);
        return getSendCMD(CMD_LIGHT_SET, send);
    }

    /// <summary>
    /// 柜号设置命令 格子
    /// </summary>
    /// <returns></returns>
    public byte[] LatticeNumSet(boolean invalid, String hexAddr, String hexRow, String hexMaxColum)
    {
        m_iCmdType = CMD_CABINETNO_SET;
        byte bValidData = 0x01;
        if (invalid) {
            bValidData = 0x00;
        }
        byte[] bAddrArry = TcnUtility.hexStringToBytes(hexAddr);
        byte bAddr = bAddrArry[0];
        byte[] bRowrArry = TcnUtility.hexStringToBytes(hexRow);
        byte bRow = bRowrArry[0];
        byte[] bColumrArry = TcnUtility.hexStringToBytes(hexMaxColum);
        byte bColum = bColumrArry[0];
        byte[] send = new byte[] { bAddr, bRow, bColum, bValidData,0, RandNum(), RandNum() };
        send[4] = (byte)((((bAddr + bRow) * 2 + send[2]) * 4 + send[3]) * 8);
        return getSendCMD(CMD_LATTICE_NUM_SET, send);
    }

    /// <summary>
    /// 开关柜子
    /// </summary>
    /// <returns></returns>
    public byte[] LatticeOnOff(String hexAddr, int BoxNo)
    {
        m_iCmdType = CMD_CABINETNO_ON;
        m_bIsShipping = true;
        m_iShipSlotNo = BoxNo;
        byte[] bAddrArry = TcnUtility.hexStringToBytes(hexAddr);
        if ((null == bAddrArry) || (bAddrArry.length < 1)) {
            return null;
        }
        byte bAddr = bAddrArry[0];
        byte bBoxNo = (byte)BoxNo;
        byte[] send = new byte[] { bAddr, bBoxNo, RandNum(), RandNum(), 0, RandNum(), RandNum() };
        send[4] = (byte)((((bAddr + bBoxNo) * 2 + send[2]) * 4 + send[3]) * 8);
        return getSendCMD(CMD_LatticeOnOff, send);
    }


    private boolean hasGroup(int group) {
        boolean bRet = false;
        for (String data :m_groupList) {
            if (Integer.parseInt(data,16) == group) {
                bRet = true;
            }
        }
        return bRet;
    }

    private int getRealSlotNo(int slot,String addr) {
        int slotNo = slot;
        if (addr.equals("00")) {
            slotNo = slot;
        } else if (addr.equals("01")) {
            slotNo = slot-100;
        } else if (addr.equals("02")) {
            slotNo = slot-200;
        } else if (addr.equals("03")) {
            slotNo = slot-300;
        } else if (addr.equals("04")) {
            slotNo = slot-400;
        } else if (addr.equals("05")) {
            slotNo = slot-500;
        }  else if (addr.equals("06")) {
            slotNo = slot-600;
        } else if (addr.equals("07")) {
            slotNo = slot-700;
        } else if (addr.equals("08")) {
            slotNo = slot-800;
        }
        else {

        }
        return slotNo;
    }

    private int getSlotNoToSend(int slot,String addr) {
        int slotNo = slot;
        if (addr.equals("00")) {
            slotNo = slot;
        } else if (addr.equals("01")) {
            slotNo = slot+100;
        } else if (addr.equals("02")) {
            slotNo = slot+200;
        } else if (addr.equals("03")) {
            slotNo = slot+300;
        } else if (addr.equals("04")) {
            slotNo = slot+400;
        } else if (addr.equals("05")) {
            slotNo = slot+500;
        }  else if (addr.equals("06")) {
            slotNo = slot+600;
        } else if (addr.equals("07")) {
            slotNo = slot+700;
        } else if (addr.equals("08")) {
            slotNo = slot+800;
        }
        else {

        }
        return slotNo;
    }

}
